#include <windows.h>
#include <sddl.h>
#include <iostream>
#include <lm.h>
#include <stdio.h>
#include <tchar.h>

void createproc(wchar_t execName[]);
void GetAccountSid(LPCTSTR lpName, DWORD* szSid);
BOOL EnableTcbPrivilege();

void PrintError(LPTSTR lpszFunction) {
    LPVOID lpMsgBuf;
    DWORD dw = GetLastError();
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR)&lpMsgBuf, 0, NULL);
    _tprintf(_T("%s failed with error %d: %s\n"),
        lpszFunction, dw, (LPTSTR)lpMsgBuf);
    LocalFree(lpMsgBuf);
}

int wmain(int argc, wchar_t* argv[]) {
    if (argc == 2 or argc == 3) {
        EnableTcbPrivilege();

        system("net start \"Secondary Logon\"");
        system("net start \"RpcSs\"");

        HANDLE hToken = NULL;
        HANDLE hTokenDup = NULL;

        // 使用SID字符串来代表TrustedInstaller: L"S-1-5-80-956008086-3406848970-3468268847-18515"
        LPTSTR lpName = _tcsdup(argv[1]);
        DWORD pSid = NULL;

        GetAccountSid(lpName, &pSid);

        _tprintf(_T("SID for user '%s': %ld\n"), lpName, &pSid);

        // 使用SID创建Logon token
        if (!LogonUserW(L"Username", L".", L"Password", LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, &hToken)) {
            printf("LogonUser failed: %lu\n", GetLastError());
            LocalFree(&pSid);
            return 1;
        }

        // Duplicate the token to make it usable in this process
        if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hTokenDup)) {
            printf("DuplicateTokenEx failed: %lu\n", GetLastError());
            CloseHandle(hToken);
            LocalFree(&pSid);
            return 1;
        }

        // Close the original token as we now have a duplicate
        CloseHandle(hToken);

        if (!ImpersonateLoggedOnUser(hTokenDup)) {
            printf("ImpersonateLoggedOnUser failed: %lu\n", GetLastError());
            CloseHandle(hTokenDup);
            LocalFree(&pSid);
            return 1;
        }

        // 在这里执行需要高级权限的操作，例如文件操作等。
        // 例如：创建一个文件或者修改系统配置等。
        if (argc == 3)
        {
            createproc(argv[2]);
        }
        else
        {
            WCHAR cmdLine[] = _T("cmd /k start");
            createproc(cmdLine);
        }

        // 停止模拟并恢复正常的身份验证状态。
        RevertToSelf();

        CloseHandle(hTokenDup);
        LocalFree(&pSid);
    }
    else {
        printf("arg count must be 2 or 3.");
    }
}


void createproc(wchar_t execName[])
{
    // 定义进程信息结构体
    PROCESS_INFORMATION processInfo;

    // 定义启动信息结构体
    STARTUPINFO startupInfo;

    // 初始化结构体
    ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
    startupInfo.cb = sizeof(STARTUPINFO);

    // 要启动的程序路径(示例为记事本)
    STARTUPINFO si = { sizeof(si) };

    // 启动新进程
    if (!CreateProcess(
        NULL,                   // 模块名(可为NULL)
        LPWSTR(execName), // 命令行参数
        NULL,                   // 进程安全属性
        NULL,                   // 线程安全属性
        FALSE,                  // 不继承句柄
        0,                      // 无创建标志
        NULL,                   // 使用父进程环境块
        NULL,                   // 使用父进程当前目录
        &startupInfo,           // 启动信息
        &processInfo))          // 进程信息
    {
        std::cerr << "CreateProcess failed: " << GetLastError() << std::endl;
    }

    // 关闭进程和线程句柄
    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);
}


BOOL EnableTcbPrivilege() {
    HANDLE hToken;
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
        return FALSE;

    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    BOOL result = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
    CloseHandle(hToken);
    return result && (GetLastError() == ERROR_SUCCESS);
}

void GetAccountSid(LPCTSTR lpName, DWORD* szSid) {
    SID_NAME_USE sidType;
    DWORD cbSid = 0;
    DWORD cchDomainName = 0;
    LPTSTR szDomainName = NULL;
    PSID pSid = NULL;

    // 第一次调用获取所需缓冲区大小
    LookupAccountName(NULL, lpName, NULL, szSid, NULL, &cchDomainName, &sidType);

    pSid = (PSID)LocalAlloc(LPTR, cbSid);
    szDomainName = (LPTSTR)LocalAlloc(LPTR, cchDomainName * sizeof(TCHAR));

    if (LookupAccountName(NULL, lpName, pSid, szSid, szDomainName, &cchDomainName, &sidType)) {
        LocalFree(pSid);
        LocalFree(szDomainName);
        return;
    }

    LocalFree(pSid);
    LocalFree(szDomainName);
    *szSid = NULL;
}
